﻿using System.Collections.Generic;
using System.Drawing;

using DBF_ReadWrite;

namespace OpenShape
{
    class Layer
    {
        public Layer()
        {
            m_isOn = true;
            m_isLabelOn = false;
            m_MinScale = 0;
            m_MaxScale = 100000;
            //m_DataSource = null;
            m_MBR.xmax = m_MBR.xmin = m_MBR.ymax = m_MBR.ymin = 0;
            m_nShapeType = 0;
            m_bOpen = false;
            //m_label = null;
            //m_SpatialObject = null;
          
            m_DrawProperties.penThickness = 0.4f;
            m_DrawProperties.penColor = Color.Black;
            m_DrawProperties.brushColor = Color.Lavender;
        }

        public Shapefile m_DataSource = new Shapefile();
        public string m_DataSourceName;
        public int m_nRecords;
        public int m_nShapeType;
        public GeoRect m_MBR = new GeoRect();
        public List<object> m_SpatialObject = new List<object>();
        //public DataTable m_DBF;
        public DBF_Struct m_DBF;
        public bool m_bOpen;
        public Labeler m_label = new Labeler();
        public bool m_isOn;
        public bool m_isSelect;
        public bool m_isLabelOn;
        public int m_MaxScale;
        public int m_MinScale;
        public string m_FieldName;

        public struct DrawProperties
        {
            public float penThickness; //펜두께 (선두께)
            public Color penColor;  //펜색상 (선색상)
            public Color brushColor;  // 브러쉬 컬러 (면색상)
        }
        public DrawProperties m_DrawProperties = new DrawProperties();

        public Font fonts = new Font(
            new FontFamily("Arial"),
            10,
            FontStyle.Regular,
            GraphicsUnit.Point);
        public Color pFontColor = Color.Black;

        public void Draw(Graphics g, Scaler sc)
        {
            if ((m_isOn == false) || (sc.nowRatio < m_MinScale) || (sc.nowRatio > m_MaxScale))
                return;

            double sx, sy;

            //Graphics g = e.Graphics;
            SolidBrush blueBrush = new SolidBrush(m_DrawProperties.brushColor);
            Pen pPen = new Pen(m_DrawProperties.penColor, m_DrawProperties.penThickness);
            switch (m_nShapeType)
            {
                case 1: // point

                    for (int i = 0; i < m_nRecords; i++)
                    {
                        PointF pt = new PointF();
                        GeoPoint m_SO = (GeoPoint)m_SpatialObject[i];
                        sc.WorldToDevice(m_SO.Points[0].X, m_SO.Points[0].Y, out sx, out sy);
                        pt.X = (float)sx;
                        pt.Y = (float)sy;
                        RectangleF temp_drawPt = new RectangleF(pt.X - 1.5f, pt.Y - 1.5f, 3f, 3f);
                        if (blueBrush.Color != Color.Empty)
                        {
                            g.FillEllipse(blueBrush, temp_drawPt);
                        }
                        g.DrawEllipse(pPen, temp_drawPt);
                    }

                    break;

                case 3: // polyline

                    for (int i = 0; i < m_nRecords; i++)
                    {
                        GeoPolyline m_SO = (GeoPolyline)m_SpatialObject[i];
                        int NumPoints = m_SO.NumPoints;
                        int NumParts = m_SO.NumParts;
                        PointF[] pTempPoint = new PointF[NumPoints];
                        int[] pVertex = new int[NumParts];

                        // 한 feature의 점을 pTempPoint에 저장
                        for (int j = 0; j < NumPoints; j++)
                        {
                            sc.WorldToDevice(m_SO.Points[j].X, m_SO.Points[j].Y, out sx, out sy);
                            pTempPoint[j].X = (float)sx;
                            pTempPoint[j].Y = (float)sy;

                            //GDI+에서는 DrawLines를 사용하기에 버텍스는 필요없고 각각의 폴리라인을 그려야됨.

                        }
                        g.DrawLines(pPen, pTempPoint);
                    }
                    break;

                case 5: // polygon

                    for (int i = 0; i < m_nRecords; i++)
                    {
                        GeoPolygon m_SO = (GeoPolygon)m_SpatialObject[i];
                        int NumPoints = m_SO.NumPoints;
                        int NumParts = m_SO.NumParts;
                        PointF[] pTempPoint = new PointF[NumPoints];
                        int[] pVertex = new int[NumParts];

                        // 한 feature의 점을 pTempPoint에 저장

                        for (int j = 0; j < NumPoints; j++)
                        {
                            sc.WorldToDevice(m_SO.Points[j].X, m_SO.Points[j].Y, out sx, out sy);
                            pTempPoint[j].X = (float)sx;
                            pTempPoint[j].Y = (float)sy;

                            //GDI+에서는 DrawLines를 사용하기에 버텍스는 필요없고 각각의 폴리라인을 그려야됨.

                        }
                        // 버텍스 수를 구하는 과정
                        for (int j = 0; j < NumParts; j++)
                        {

                            if (j == NumParts - 1)
                            {
                                pVertex[j] = NumPoints - m_SO.Parts[j];
                                PointF[] pTempPartPoint = new PointF[pVertex[j]];
                                for (int k = m_SO.Parts[j]; k < NumPoints; k++)
                                {
                                    pTempPartPoint[k - m_SO.Parts[j]] = pTempPoint[k];
                                }
                                if (blueBrush.Color != Color.Empty)
                                {
                                    g.FillPolygon(blueBrush, pTempPartPoint);
                                }
                                g.DrawPolygon(pPen, pTempPartPoint);

                            }
                            else
                            {
                                pVertex[j] = m_SO.Parts[j + 1] - m_SO.Parts[j];
                                PointF[] pTempPartPoint = new PointF[pVertex[j]];
                                for (int k = m_SO.Parts[j]; k < m_SO.Parts[j + 1]; k++)
                                {
                                    pTempPartPoint[k - m_SO.Parts[j]] = pTempPoint[k];
                                }
                                if (blueBrush.Color != Color.Empty)
                                {
                                    g.FillPolygon(blueBrush, pTempPartPoint);
                                }
                                g.DrawPolygon(pPen, pTempPartPoint);
                            }
                        }
                    }
                    break;

                default:

                    break;
            }
        }

        public void LayerLabelDraws(Graphics g, Scaler sc)
        {
            if ((m_isOn == false) || (sc.nowRatio < m_MinScale) || (sc.nowRatio > m_MaxScale))
                return;
            if (m_isLabelOn == true)
            {
                m_label.ReadField(this, m_FieldName);
                m_label.draw(g, sc, this);
            }
        }
        
        public void OpenFile(string filename, string fType)
        {
            m_DataSourceName = filename;
            if (m_bOpen == false)
            {
                if (fType == "shp")
                {
                    Shapefile temp_Shape = new Shapefile ();
                    temp_Shape.LoadData(filename, this);
                    m_DataSource = temp_Shape;
                    m_label.CalculateLabelPoint(this); 
                    m_bOpen = true;
                }
                else if (fType == "db")
                {

                }
            }
        }

    }
}
